package com.snail.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.snail.exception.BizException;
import com.snail.mapper.SysPermissionMapper;
import com.snail.model.pojo.user.SysPermission;
import com.snail.model.pojo.user.SysRolePermission;
import com.snail.model.pojo.user.SysUserRole;
import com.snail.model.vo.user.MenuVO;
import com.snail.result.Result;
import com.snail.result.ResultCode;
import com.snail.service.SysRolePermissionService;
import com.snail.service.SysUserRoleService;
import com.snail.service.SysPermissionService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 权限服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission>
    implements SysPermissionService {

    private final SysUserRoleService userRoleService;
    private final SysRolePermissionService rolePermissionService;
    /**
     * 根据用户ID获取菜单树
     */
    @Override
    //rollbackFor = Exception.class 意思是遇到任何异常就回滚
    @Transactional(rollbackFor = Exception.class)
    public List<SysPermission> getUserMenuTree(Long userId) {
        // 1. 查询用户所有角色ID
        List<Long> roleIds = userRoleService.lambdaQuery()
                .eq(SysUserRole::getUserId, userId)
                .list()   //这里是查到的当前登录用户的角色ID集合
                .stream()
                //这里是用stream流调用出.map的方法，将用userId查出来的roleId集合重新放进一个新的Stream<Long>中
                .map(SysUserRole::getRoleId)
                //collect 是结束stream流的方法，并将stream流中的元素收集到一个集合中
                .collect(Collectors.toList());
        // 如果用户没有角色 ,抛出异常
        if (roleIds.isEmpty()) {
            throw new BizException( "用户未分配任何角色");
        }

        // 2. 查询所有角色拥有的权限ID
        List<Long> permissionIds = rolePermissionService.lambdaQuery()
                //查询出来的roId可能有多个，用in方法将对应的权限都查出来
                .in(SysRolePermission::getRoleId, roleIds)
                .list()
                .stream()
                .map(SysRolePermission::getPermissionId)
                .distinct() //有可能有重复的权限ID，这里用distinct方法去重
                .collect(Collectors.toList());

        if (permissionIds.isEmpty()) {
            throw new BizException( "用户没有任何权限");
        }

        // 3. 查询权限表，过滤菜单类型（假设 type=1 是菜单）this代表当前类
        List<SysPermission> permissions = this.lambdaQuery()
                .in(SysPermission::getId, permissionIds)
                .list();
        log.info("权限表：{}", permissions);
        // 4. 组装成树形菜单
        return buildTree(permissions, 0L);
    }


    /**
     * 删除菜单及其角色权限关系
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenuAndRolePermission(Long id) {
        // 先查所有子菜单
        List<SysPermission> childMenus = this.lambdaQuery()
                .eq(SysPermission::getParentId, id)
                .list();

        for (SysPermission child : childMenus) {
            deleteMenuAndRolePermission(child.getId());
        }

        // 1. 删除角色权限中间表中所有有关此菜单的记录
        LambdaQueryWrapper<SysRolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRolePermission::getPermissionId, id);
        rolePermissionService.remove(wrapper); // 注入 SysRolePermissionService

        // 2. 删除菜单本身（逻辑删除）
        this.removeById(id);
    }


    /**
     * 组装树形菜单
     */
    private List<SysPermission> buildTree(List<SysPermission> permissions, Long parentId) {
        List<SysPermission> tree = new ArrayList<>();
        for (SysPermission permission : permissions) {
            if (Objects.equals(parentId, permission.getParentId())) {
                List<SysPermission> children = buildTree(permissions, permission.getId());
                permission.setChildren(children);
                tree.add(permission);
            }
        }
        log.info("组装树形菜单：{}", tree);
        return tree;
    }


}




